package com.example.exercise.rule;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExpInit {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExpInit.class);

    public static String ruleInit(String rule) {
        rule = rule.replace("'", "\"")
                .replace("\n", " ")
                .replace("\t", " ")
                .replace("'", "\"")
                .replace("==", "=")
                .replace("<>", "!=")
                .replace("=", "==")
                .replace("<==", "<=")
                .replace(">==", ">=")
                .replace("!==", "!=")
                .replaceAll("\\s+", " ")
                .replaceAll(" [Aa][Nn][Dd] ", " && ")
                .replaceAll(" [Oo][Rr] ", " || ")
                .replaceAll(" [Ii][Nn] ", " in ")
                .replaceAll(" [Nn][Oo][Tt] [Ii][Nn] ", " not in ");
        String replaceNotIn = replaceNotIn(rule);
        if (replaceNotIn != null && !"".equals(replaceNotIn.trim())) {
            return replaceIn(replaceNotIn);
        }
        return null;
    }

    public static String replaceNotIn(String rule) {
        int startIndex = rule.indexOf(" not in (");
        if (startIndex == 0) {
            LOGGER.error("表达式：" + rule + " 错误");
            return null;
        } else if (startIndex == -1) {
            return rule;
        } else {
            String rightRule = rule.substring(startIndex);
            int rightInd = rightRule.indexOf(')');
            if (rightInd == -1) {
                LOGGER.error("表达式：" + rule + " 错误");
                return null;
            } else {
                String leftRule = rule.substring(0, startIndex);
                int ind = leftRule.lastIndexOf(" ");
                String fieldName = leftRule.substring(ind + 1).replace("(", "");
                String elements = rightRule.substring(9, rightInd);
                String beginStr = leftRule.substring(0, leftRule.lastIndexOf(fieldName));
                String endStr = rightRule.substring(rightInd + 1);

                StringBuilder stringBuilder = new StringBuilder(beginStr);
                String[] elementArr = elements.split(",");
                if (elementArr.length == 1) {
                    stringBuilder.append(fieldName).append(" != ").append(elementArr[0].trim());
                } else {
                    stringBuilder.append("(");
                    for (String str : elementArr) {
                        stringBuilder.append(fieldName).append(" != ").append(str.trim()).append(" && ");
                    }
                    int len = stringBuilder.length();
                    stringBuilder.delete(len - 4, len).append(")");
                }
                stringBuilder.append(endStr);
                return replaceNotIn(stringBuilder.toString());
            }
        }
    }

    public static String replaceIn(String rule) {
        int startIndex = rule.indexOf(" in (");
        if (startIndex == 0) {
            LOGGER.error("表达式：" + rule + " 错误");
            return null;
        } else if (startIndex == -1) {
            return rule;
        } else {
            String rightRule = rule.substring(startIndex);
            int rightInd = rightRule.indexOf(')');
            if (rightInd == -1) {
                LOGGER.error("表达式：" + rule + " 错误");
                return null;
            } else {
                String leftRule = rule.substring(0, startIndex);
                int ind = leftRule.lastIndexOf(" ");
                String fieldName = leftRule.substring(ind + 1).replace("(", "");
                String elements = rightRule.substring(5, rightInd);
                String beginStr = leftRule.substring(0, leftRule.lastIndexOf(fieldName));
                String endStr = rightRule.substring(rightInd + 1);

                StringBuilder stringBuilder = new StringBuilder(beginStr);
                String[] elementArr = elements.split(",");
                if (elementArr.length == 1) {
                    stringBuilder.append(fieldName).append("==").append(elementArr[0].trim());
                } else {
                    stringBuilder.append("(");
                    for (String str : elementArr) {
                        stringBuilder.append(fieldName).append("==").append(str.trim()).append(" || ");
                    }
                    int len = stringBuilder.length();
                    stringBuilder.delete(len - 4, len).append(")");
                }
                stringBuilder.append(endStr);
                return replaceIn(stringBuilder.toString());
            }
        }
    }

    public static boolean verifyRuleExpression(String rule) {
        if (rule == null || "".equals(rule.trim())) {
            LOGGER.error("规则表达式不能为空");
            return false;
        }
        if (!rule.contains("(") && !rule.contains(")")) {
            return validateExpressionOne(rule);
        }
        if (deleteBrackets(rule) == null) {
            return false;
        }
        String ruleNoBrackets = rule.replace("(", "").replace(")", "");
        return validateExpressionOne(ruleNoBrackets);
    }

    public static String deleteBrackets(String rule) {
        int indRight = rule.indexOf(")");
        if (indRight == -1) {
            LOGGER.error("缺失右括号");
            return null;
        }
        String leftStr = rule.substring(0, indRight);
        int indLeft = leftStr.lastIndexOf("(");
        if (indLeft == -1) {
            LOGGER.error("缺失左括号");
            return null;
        }
        String finalStr = rule.substring(0, indLeft) + rule.substring(indRight + 1);
        if (!finalStr.contains("(") && !finalStr.contains(")")) {
            return finalStr;
        }
        return deleteBrackets(finalStr);
    }

    public static boolean validateExpressionOne(String rule) {
        String[] ruleArr = rule.split("&&|\\|\\|");
        for (String str : ruleArr) {
            String[] obj = getExp(str);
            if (obj == null) {
                return false;
            }
            if ("".equals(obj[0]) || "".equals(obj[1])) {
                LOGGER.error("有多余的逻辑连接符 and or in 等");
                return false;
            }
        }
        return true;
    }

    public static String[] getExp(String str) {
        int num = 0;
        for (char ch : str.toCharArray()) {
            if (ch == '<' || ch == '>' || ch == '=' || ch == '!') {
                num++;
            }
        }
        if (num == 1) {
            String[] arr = str.split("[<>]");
            if (arr.length == 2 && !"".equals(arr[0].trim()) && !"".equals(arr[1].trim())) {
                return new String[]{getReplacedFieldName(arr[0].trim()), arr[1].trim()};
            }
            LOGGER.error("逻辑运算符必须是>、<、=、=>、<=、!=、in、not in");
            return null;
        }
        if (num == 2) {
            String[] arr = str.split("<=|>=|==|!=");
            if (arr.length == 2 && !"".equals(arr[0].trim()) && !"".equals(arr[1].trim())) {
                return new String[]{getReplacedFieldName(arr[0].trim()), arr[1].trim()};
            }
            LOGGER.error("逻辑运算符必须是>、<、=、=>、<=、!=、in、not in");
            return null;
        }
        LOGGER.error("逻辑运算符必须是>、<、=、=>、<=、!=、in、not in");
        return null;
    }

    public static String getReplacedFieldName(String fieldName) {
        if (fieldName.contains(".")) {
            return fieldName.substring(0, fieldName.indexOf("."));
        }
        if (!fieldName.contains("_")) {
            char ch = fieldName.charAt(0);
            if (ch >= 'a' && ch <= 'z') {
                return fieldName;
            } else {
                return fieldName.toLowerCase();
            }
        } else {
            String[] fieldNameParts = fieldName.split("_");
            StringBuilder stringBuilder = new StringBuilder();
            int num = 1;
            for (String fieldNamePart : fieldNameParts) {
                if (num == 1) {
                    stringBuilder.append(fieldNamePart.toLowerCase());
                } else {
                    stringBuilder.append(fieldNamePart.substring(0, 1).toUpperCase())
                            .append(fieldNamePart.substring(1).toLowerCase());
                }
                num++;
            }
            return stringBuilder.toString();
        }
    }

}
